home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / lib / python2.6 / fpformat.py < prev    next >
Text File  |  2009-11-02  |  5KB  |  146 lines

  1. """General floating point formatting functions.
  2.  
  3. Functions:
  4. fix(x, digits_behind)
  5. sci(x, digits_behind)
  6.  
  7. Each takes a number or a string and a number of digits as arguments.
  8.  
  9. Parameters:
  10. x:             number to be formatted; or a string resembling a number
  11. digits_behind: number of digits behind the decimal point
  12. """
  13. from warnings import warnpy3k
  14. warnpy3k("the fpformat module has been removed in Python 3.0", stacklevel=2)
  15. del warnpy3k
  16.  
  17. import re
  18.  
  19. __all__ = ["fix","sci","NotANumber"]
  20.  
  21. # Compiled regular expression to "decode" a number
  22. decoder = re.compile(r'^([-+]?)0*(\d*)((?:\.\d*)?)(([eE][-+]?\d+)?)$')
  23. # \0 the whole thing
  24. # \1 leading sign or empty
  25. # \2 digits left of decimal point
  26. # \3 fraction (empty or begins with point)
  27. # \4 exponent part (empty or begins with 'e' or 'E')
  28.  
  29. try:
  30.     class NotANumber(ValueError):
  31.         pass
  32. except TypeError:
  33.     NotANumber = 'fpformat.NotANumber'
  34.  
  35. def extract(s):
  36.     """Return (sign, intpart, fraction, expo) or raise an exception:
  37.     sign is '+' or '-'
  38.     intpart is 0 or more digits beginning with a nonzero
  39.     fraction is 0 or more digits
  40.     expo is an integer"""
  41.     res = decoder.match(s)
  42.     if res is None: raise NotANumber, s
  43.     sign, intpart, fraction, exppart = res.group(1,2,3,4)
  44.     if sign == '+': sign = ''
  45.     if fraction: fraction = fraction[1:]
  46.     if exppart: expo = int(exppart[1:])
  47.     else: expo = 0
  48.     return sign, intpart, fraction, expo
  49.  
  50. def unexpo(intpart, fraction, expo):
  51.     """Remove the exponent by changing intpart and fraction."""
  52.     if expo > 0: # Move the point left
  53.         f = len(fraction)
  54.         intpart, fraction = intpart + fraction[:expo], fraction[expo:]
  55.         if expo > f:
  56.             intpart = intpart + '0'*(expo-f)
  57.     elif expo < 0: # Move the point right
  58.         i = len(intpart)
  59.         intpart, fraction = intpart[:expo], intpart[expo:] + fraction
  60.         if expo < -i:
  61.             fraction = '0'*(-expo-i) + fraction
  62.     return intpart, fraction
  63.  
  64. def roundfrac(intpart, fraction, digs):
  65.     """Round or extend the fraction to size digs."""
  66.     f = len(fraction)
  67.     if f <= digs:
  68.         return intpart, fraction + '0'*(digs-f)
  69.     i = len(intpart)
  70.     if i+digs < 0:
  71.         return '0'*-digs, ''
  72.     total = intpart + fraction
  73.     nextdigit = total[i+digs]
  74.     if nextdigit >= '5': # Hard case: increment last digit, may have carry!
  75.         n = i + digs - 1
  76.         while n >= 0:
  77.             if total[n] != '9': break
  78.             n = n-1
  79.         else:
  80.             total = '0' + total
  81.             i = i+1
  82.             n = 0
  83.         total = total[:n] + chr(ord(total[n]) + 1) + '0'*(len(total)-n-1)
  84.         intpart, fraction = total[:i], total[i:]
  85.     if digs >= 0:
  86.         return intpart, fraction[:digs]
  87.     else:
  88.         return intpart[:digs] + '0'*-digs, ''
  89.  
  90. def fix(x, digs):
  91.     """Format x as [-]ddd.ddd with 'digs' digits after the point
  92.     and at least one digit before.
  93.     If digs <= 0, the point is suppressed."""
  94.     if type(x) != type(''): x = repr(x)
  95.     try:
  96.         sign, intpart, fraction, expo = extract(x)
  97.     except NotANumber:
  98.         return x
  99.     intpart, fraction = unexpo(intpart, fraction, expo)
  100.     intpart, fraction = roundfrac(intpart, fraction, digs)
  101.     while intpart and intpart[0] == '0': intpart = intpart[1:]
  102.     if intpart == '': intpart = '0'
  103.     if digs > 0: return sign + intpart + '.' + fraction
  104.     else: return sign + intpart
  105.  
  106. def sci(x, digs):
  107.     """Format x as [-]d.dddE[+-]ddd with 'digs' digits after the point
  108.     and exactly one digit before.
  109.     If digs is <= 0, one digit is kept and the point is suppressed."""
  110.     if type(x) != type(''): x = repr(x)
  111.     sign, intpart, fraction, expo = extract(x)
  112.     if not intpart:
  113.         while fraction and fraction[0] == '0':
  114.             fraction = fraction[1:]
  115.             expo = expo - 1
  116.         if fraction:
  117.             intpart, fraction = fraction[0], fraction[1:]
  118.             expo = expo - 1
  119.         else:
  120.             intpart = '0'
  121.     else:
  122.         expo = expo + len(intpart) - 1
  123.         intpart, fraction = intpart[0], intpart[1:] + fraction
  124.     digs = max(0, digs)
  125.     intpart, fraction = roundfrac(intpart, fraction, digs)
  126.     if len(intpart) > 1:
  127.         intpart, fraction, expo = \
  128.             intpart[0], intpart[1:] + fraction[:-1], \
  129.             expo + len(intpart) - 1
  130.     s = sign + intpart
  131.     if digs > 0: s = s + '.' + fraction
  132.     e = repr(abs(expo))
  133.     e = '0'*(3-len(e)) + e
  134.     if expo < 0: e = '-' + e
  135.     else: e = '+' + e
  136.     return s + 'e' + e
  137.  
  138. def test():
  139.     """Interactive test run."""
  140.     try:
  141.         while 1:
  142.             x, digs = input('Enter (x, digs): ')
  143.             print x, fix(x, digs), sci(x, digs)
  144.     except (EOFError, KeyboardInterrupt):
  145.         pass
  146.